package com.example.myapplication.base;

import android.os.Bundle;
import android.os.Parcelable;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;



import java.io.Serializable;
import java.util.ArrayList;

/**
 * Fragment信息。
 */
public class UIFragmentInfo {

    @NonNull
    private final String mClassName;
    @Nullable
    private volatile Bundle mArgs;
    @Nullable
    private final String mTag;

    /**
     * 创建新的Fragment信息。
     *
     * @param cls Fragment类。
     */
    public UIFragmentInfo(@NonNull Class<? extends UIFragment> cls) {
        this(cls, null);
    }

    /**
     * 创建新的Fragment信息。
     *
     * @param cls Fragment类。
     * @param tag Fragment标签，或者传入{@code null}不设标签。
     */
    public UIFragmentInfo(@NonNull Class<? extends UIFragment> cls, @Nullable String tag) {
        ArgUtils.checkNonNull("cls", cls);
        mClassName = cls.getName();
        mTag = tag;
    }

    UIFragmentInfo(@NonNull String className, @Nullable Bundle args, @Nullable String tag) {
        mClassName = className;
        mArgs = args;
        mTag = tag;
    }

    /**
     * 获取Fragment类名。
     *
     * @return Fragment类名。
     */
    @NonNull
    public String getClassName() {
        return mClassName;
    }

    /**
     * 获取Fragment参数。
     *
     * @return Fragment参数。
     */
    @Nullable
    public Bundle getArguments() {
        return mArgs;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, boolean value) {
        requireArguments().putBoolean(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, byte value) {
        requireArguments().putByte(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, char value) {
        requireArguments().putChar(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, short value) {
        requireArguments().putShort(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, int value) {
        requireArguments().putInt(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, long value) {
        requireArguments().putLong(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, float value) {
        requireArguments().putFloat(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, double value) {
        requireArguments().putDouble(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable String value) {
        requireArguments().putString(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable CharSequence value) {
        requireArguments().putCharSequence(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable Parcelable value) {
        requireArguments().putParcelable(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable Parcelable[] value) {
        requireArguments().putParcelableArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putParcelableArrayListArgument(@Nullable String name,
                                                         @Nullable ArrayList<? extends Parcelable> value) {
        requireArguments().putParcelableArrayList(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putIntegerArrayListArgument(@Nullable String name,
                                                      @Nullable ArrayList<Integer> value) {
        requireArguments().putIntegerArrayList(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putStringArrayListArgument(@Nullable String name,
                                                     @Nullable ArrayList<String> value) {
        requireArguments().putStringArrayList(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putCharSequenceArrayListArgument(@Nullable String name,
                                                           @Nullable ArrayList<CharSequence> value) {
        requireArguments().putCharSequenceArrayList(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable Serializable value) {
        requireArguments().putSerializable(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable boolean[] value) {
        requireArguments().putBooleanArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable byte[] value) {
        requireArguments().putByteArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable short[] value) {
        requireArguments().putShortArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable char[] value) {
        requireArguments().putCharArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable int[] value) {
        requireArguments().putIntArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable long[] value) {
        requireArguments().putLongArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable float[] value) {
        requireArguments().putFloatArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable double[] value) {
        requireArguments().putDoubleArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable String[] value) {
        requireArguments().putStringArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable CharSequence[] value) {
        requireArguments().putCharSequenceArray(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param name  参数名。
     * @param value 参数值。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArgument(@Nullable String name, @Nullable Bundle value) {
        requireArguments().putBundle(name, value);
        return this;
    }

    /**
     * 添加Fragment参数。
     *
     * @param args 参数{@link Bundle}对象。
     * @return 此对象，用于链式调用。
     */
    @NonNull
    public UIFragmentInfo putArguments(@NonNull Bundle args) {
        ArgUtils.checkNonNull("args", args);
        requireArguments().putAll(args);
        return this;
    }

    /**
     * 获取Fragment标签。
     *
     * @return Fragment标签，如果没有则返回{@code null}。
     */
    @Nullable
    public String getTag() {
        return mTag;
    }

    @NonNull
    private Bundle requireArguments() {
        return mArgs == null ? (mArgs = new Bundle()) : mArgs;
    }

}
